package com.fengzheng.basic.common.config.authorization.login;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fengzheng.basic.model.po.SysUserPo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author liht
 * @date 2022/3/25 2:01 下午
 */
@Slf4j
public class LoginAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private final ObjectMapper objectMapper;

    private final AuthenticationManager authenticationManager;

    public static LoginAuthenticationFilter create(
            AuthenticationManager authenticationManager, ObjectMapper objectMapper,String loginUrl,
            AuthenticationSuccessHandler successHandler,
            AuthenticationFailureHandler failureHandler) {
        LoginAuthenticationFilter info = new LoginAuthenticationFilter(authenticationManager,objectMapper,loginUrl);
        info.setAuthenticationSuccessHandler(successHandler);
        info.setAuthenticationFailureHandler(failureHandler);
        return info;
    }

    private LoginAuthenticationFilter(AuthenticationManager authenticationManager,ObjectMapper objectMapper,String loginUrl) {
        super(new AntPathRequestMatcher(loginUrl, HttpMethod.POST.toString()));
        this.objectMapper = objectMapper;
        this.authenticationManager = authenticationManager;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException,IOException,ServletException{

        SysUserPo users;
        try{
            // 从body中取出,参数是在请求体中使用json形式传入的
            users = objectMapper.readValue(request.getInputStream(), SysUserPo.class);
        }catch (Exception e){
            throw new UsernameNotFoundException("参数错误");
        }

        try {
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(users.getAccount(), users.getPassword());
            // 模仿UsernamePasswordAuthenticationFilter的方式，将用户名密码进行比较
            Authentication authentication = authenticationManager.authenticate(token);
            return authentication;
        } catch (InternalAuthenticationServiceException e){
            throw new InternalAuthenticationServiceException(e.getMessage());
        } catch (AuthenticationException e){
            log.error("登陆异常: {}", e.getMessage(), e);
            throw new UsernameNotFoundException("用户名密码错误");
        }
    }

}
